package edu.scau.payment.service;

import cn.hutool.core.util.IdUtil;
import com.alipay.api.*;
import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.scau.core.Enum.PaymentMethod;
import edu.scau.core.constants.AjaxResult;
import edu.scau.core.exection.BusinessProcessException;
import edu.scau.core.util.RedisCache;
import edu.scau.core.util.ServletUtils;
import edu.scau.payment.config.AliPayConfig;
import edu.scau.payment.domain.Payment;
import edu.scau.payment.mapper.PaymentMapper;
import edu.scau.payment.vo.PaymentVo;
import edu.scau.system.service.TokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Slf4j
public class PaymentServiceImpl implements PaymentService{
    @Autowired
    private AliPayConfig aliPayConfig;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private PaymentMapper paymentMapper;
    @Override
    public Payment createPayment(String orderId,double amount) {
        Payment payment=new Payment();
        //支付金额，方式
        payment.setAmount(amount);
        payment.setPaymentMethod(PaymentMethod.Alipay.getSignal());
        //id
        String paymentId="payment-"+ IdUtil.getSnowflakeNextId();
        payment.setPaymentId(paymentId);
        //关联order
        payment.setOrderId(orderId);
        return payment;
    }

    /**
     * 获取支付宝配置信息
     * @return
     */
    @Override
    public AlipayConfig getAlipayConfig() {
        String privateKey  = aliPayConfig.getMerchantPrivateKey();
        String alipayPublicKey = aliPayConfig.getAlipayPublicKey();
        AlipayConfig newAlipayConfig = new AlipayConfig();
        newAlipayConfig.setServerUrl(aliPayConfig.getGatewayUrl());
        newAlipayConfig.setAppId(aliPayConfig.getAppId());
        newAlipayConfig.setPrivateKey(privateKey);
        newAlipayConfig.setFormat("json");
        newAlipayConfig.setAlipayPublicKey(alipayPublicKey);
        newAlipayConfig.setCharset("UTF-8");
        newAlipayConfig.setSignType("RSA2");
        return newAlipayConfig;
    }

    /**
     * 获取客户端client
     * @return
     */
    AlipayClient getAlipayClient() throws AlipayApiException{
       return new DefaultAlipayClient(this.getAlipayConfig());
    }

    /**
     * 创建+支付
     * alipay.trade.page.pay  AlipayTradePagePayRequest
     * totalAmount sale总体金额
     * @param
     * @return form 支付表单,需要转移
     */
    @Override
    public String createAndPay(Payment successPayment,Payment pendingPayment ) throws AlipayApiException {
        AlipayClient alipayClient = this.getAlipayClient();
        // 构造请求参数以调用接口
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();

        //商户订单号，两个订单对应同一个orderid
        String out_trade_no = successPayment.getOrderId();
        if(out_trade_no.isEmpty()){
            throw new AlipayApiException("订单ID为空");
        }
        //付款金额
        double amount=successPayment.getAmount();
        if(pendingPayment!=null){
            amount+=pendingPayment.getAmount();
        }
        String total_amount =String.valueOf(amount);
        //订单名称，必填
        String subject = "'超衣库'服装购物";
        //商品描述，可空
        String body = "在'超衣库'消费"+total_amount+"元";
        String timeout = "20m";

        request.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                + "\"total_amount\":\""+ total_amount +"\","
                + "\"subject\":\""+ subject +"\","
                + "\"body\":\""+ body +"\","
                + "\"timeout_express\":\""+timeout+"\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

        String returnUrl = "http://8.134.74.245:18084/page/query?" ;
        request.setReturnUrl(returnUrl); //同步回调
        //异步入库 无效果
        //调用异步方法
//        String notifyUrl = "http://10.144.165.46:8081/alipay/notify"; // 接收支付宝异步通知的接口
//        request.setNotifyUrl(notifyUrl);

        AlipayTradePagePayResponse response = alipayClient.pageExecute(request, "POST");
        String form = response.getBody();
//        System.out.println(form);
        log.info(form);

        if (response.isSuccess()) {
           return form;
        }
        throw new AlipayApiException("订单支付sdk调用失败!");
    }

    /**
     * 异步方法
     * 更新[ay\order\sale状态
     * sale\order\payment入库
     * @return
     */
    @Override
    @Async
    public int asyncNotify() {
        return 0;
    }

    /**
     * 获取订单支付详情
     * @param orderId
     * @return true 已支付
     */
    @Override
    public boolean queryManualByOrderID(String orderId) throws AlipayApiException, JsonProcessingException {
        AlipayClient alipayClient = this.getAlipayClient();
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
        model.setOutTradeNo(orderId);
        List<String> queryOptions = new ArrayList<>();
        queryOptions.add("trade_settle_info");
        model.setQueryOptions(queryOptions);
        request.setBizModel(model);
        //查询订单状态
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        //解析
        Map<String,Object> resultMap=this.paseMap(response);
        if (response.isSuccess()) {
            if(Objects.equals((String) resultMap.get("trade_status"), "TRADE_SUCCESS")){
                return true;
            }
            if(Objects.equals((String) resultMap.get("trade_status"), "TRADE_CLOSED")){
                return false;
            }
        }
        log.info("queryManualByOrderID sdk调用失败");
        throw new AlipayApiException("querySdk调用出错");
    }

    /**
     * 支付之后完善payment的信息
     */
    @Override
    public Payment updatePaymentMsgAfterPay(String orderId,Map resultMap) throws AlipayApiException, JsonProcessingException {
        Payment payment=new Payment();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if(Objects.equals((String) resultMap.get("trade_status"), "TRADE_SUCCESS")){
            String tradeId=(String) resultMap.get("trade_no");
//            Date payTime= new Date((String) resultMap.get("send_pay_date"));
            Date payTime=null;
            try{
                payTime= formatter.parse((String) resultMap.get("send_pay_date"));
            }catch (ParseException e){
                log.error(e.getLocalizedMessage());
            }
            payment.setTradeId(tradeId);
            payment.setPayTime(payTime);
            return payment;
        }
        return null;
    }





    public Map queryByOrderID(String orderId) throws AlipayApiException, JsonProcessingException {
        AlipayClient alipayClient = this.getAlipayClient();
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
        model.setOutTradeNo(orderId);
        List<String> queryOptions = new ArrayList<>();
        queryOptions.add("trade_settle_info");
        model.setQueryOptions(queryOptions);
        request.setBizModel(model);
        //查询订单状态
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        //解析
        Map<String,Object> resultMap=this.paseMap(response);
        if (response.isSuccess()) {
            if(Objects.equals((String) resultMap.get("trade_status"), "TRADE_SUCCESS")){
                return resultMap;
            }
        }
        log.info("paymentServiceImpl.queryByOrderID","查询订单sdk调用失败");
//        throw new AlipayApiException("querySdk调用出错");
        return  null;
    }

    /**
     * 商品退货退款
     * @param outTradeId 交易订单id-->successOrderId
     * @param refundAmount 退款金额
     * @param desc 退款理由
     * @return 结果
     */
    @Override
    public Map refund(String outTradeId, double refundAmount, String desc,String refundId) throws AlipayApiException, JsonProcessingException, BusinessProcessException{
        AlipayClient alipayClient = this.getAlipayClient();

        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();

        model.setOutTradeNo(outTradeId);
        BigDecimal fee=new BigDecimal(refundAmount);
        model.setRefundAmount(String.valueOf(fee));
        model.setRefundReason(desc);
        model.setOutRequestNo(refundId);
        List<String> queryOptions = new ArrayList<String>();
        queryOptions.add("refund_detail_item_list");
        model.setQueryOptions(queryOptions);

        request.setBizModel(model);

        AlipayTradeRefundResponse response = alipayClient.execute(request);
        //System.out.println(response.getBody());
        log.info(response.getBody());
        log.info(response.getSubMsg());
        Map resultMap=this.paseMapOfRefund(response);
        if (response.isSuccess()) {
            log.info("paymentServiceImpl.refund接口调用成功");
            return resultMap;
        } else {
            log.info("paymentServiceImpl.refund接口调用失败");
            throw new BusinessProcessException(response.getSubMsg());
        }
    }

    @Override
    public Map queryRefundStatus(String refundId,String orderId) throws AlipayApiException, JsonProcessingException {
        AlipayClient alipayClient = this.getAlipayClient();
        AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
        AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();
        // 设置商户订单号
        model.setOutTradeNo(orderId);
        // 设置退款请求号
        model.setOutRequestNo(refundId);

        List<String> queryOptions = new ArrayList<String>();
        queryOptions.add("refund_detail_item_list");
        model.setQueryOptions(queryOptions);

        request.setBizModel(model);

        AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
        System.out.println(response.getBody());
        Map resultMap=this.paseMapOfRefundQuery(response);
        Map<String,Object> data=new HashMap<>();
        if (response.isSuccess()) {
            data.put("out_request_no", resultMap.get("out_request_no"));
//            data.put("退款状态", resultMap.get("refund_status"));
            data.put("refund_status", resultMap.get("refund_status"));
//            data.put("订单总额", resultMap.get("total_amount"));
            data.put("orderAmount", resultMap.get("total_amount"));
//            data.put("退款金额", resultMap.get("refund_amount"));
            data.put("refundAmount", resultMap.get("refund_amount"));
            log.info("退款接口查询成功");
        } else {
            log.info("退款接口查询失败");
            data.put("msg",resultMap.get("sub_msg"));
        }
        return data;
    }

    /**
     * 解析支付宝sdk返回的json
     * trade_status
     * WAIT_BUYER_PAY： 交易创建后，如果买家未付款，则进入 WAIT_BUYER_PAY 状态。
     * TRADE_SUCCESS： 买家完成支付后，交易进入 TRADE_SUCCESS 状态。
     * TRADE_FINISHED： 在一定时间后，交易自动进入 TRADE_FINISHED 状态（如果满足条件）。
     * TRADE_CLOSED： 如果买家未付款超时，或者商家主动关闭交易，则交易进入 TRADE_CLOSED 状态。
     * @param response
     * @return
     * @throws JsonProcessingException
     */
    public Map<String, Object>  paseMap(AlipayResponse response) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> responseMap = mapper.readValue(response.getBody(), Map.class);

        return (Map<String, Object>) responseMap.get("alipay_trade_query_response");
    }

    public Map<String, Object>  paseMapOfRefund(AlipayResponse response) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> responseMap = mapper.readValue(response.getBody(), Map.class);

        return (Map<String, Object>) responseMap.get("alipay_trade_refund_response");
    }

    public Map<String,Object> paseMapOfRefundQuery(AlipayResponse response) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> responseMap = mapper.readValue(response.getBody(), Map.class);

        return (Map<String, Object>) responseMap.get("alipay_trade_fastpay_refund_query_response");
    }
    /**
     *
     */
    void destroySaleInRedis(){

    }

    @Override
    public List<PaymentVo> listAll() {
        return paymentMapper.listAll();
    }
    @Override
    public PaymentVo findPaymentByPaymentId(String paymentId) {
        return paymentMapper.findPaymentByPaymentId(paymentId);
    }

    @Override
    public int updatePayment(Payment payment) {
        String updateBy=tokenService.getLoginUser(ServletUtils.getRequest()).getUsername();
        Date updateDate=new Date();
        if(!this.isExisted(payment.getPaymentId())){
            throw  new IllegalArgumentException("订单不存在！");
        }
        payment.setUpdateBy(updateBy);
        payment.setUpdateTime(updateDate);
        return paymentMapper.updatePayment(payment);
    }

    @Override
    public int deletePaymentById(String paymentId) {
        return paymentMapper.deletePaymentById(paymentId);
    }

    @Override
    public int insertPayment(Payment payment) {
        String createBy=tokenService.getLoginUser(ServletUtils.getRequest()).getUsername();
        Date createDate=new Date();
        int isDeleted=0;
        if(payment.getPaymentId().isEmpty()){
            throw  new IllegalArgumentException("订单编号不能为空！");
        }
        if(this.isExisted(payment.getPaymentId())){
            throw  new IllegalArgumentException("订单编号重复！");
        }
        payment.setCreateBy(createBy);
        payment.setCreateTime(createDate);
        payment.setIsDeleted(isDeleted);
        int res= paymentMapper.insertPayment(payment);
        return res;
    }

    /**
     *
     * @param paymentId
     * @return true 存在
     */
    @Override
    public boolean isExisted(String paymentId) {
        return paymentMapper.isExisted(paymentId)>0;
    }



    public Map refund(String orderId,double amount){
        return new HashMap();
    }

}
